home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / lev.c < prev    next >
C/C++ Source or Header  |  1997-05-02  |  16KB  |  495 lines

  1. /* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
  2. /* lev.c */
  3.  
  4. #include "glob.h"
  5.  
  6. /* Functions dealing with dungeon and country levels aside from actual
  7. level structure generation */
  8.  
  9.  
  10. /* monsters for tactical encounters */
  11. void make_country_monsters(terrain)
  12. short terrain;
  13. {
  14.   pml tml,ml=NULL;
  15.   static int plains[10] = 
  16.     {BUNNY,BUNNY,BLACKSNAKE,HAWK,IMPALA,WOLF,LION,BRIGAND,RANDOM};
  17.   static int forest[10] =
  18.    {BUNNY,QUAIL,HAWK,BADGER,DEER,DEER,WOLF,BEAR,BRIGAND,RANDOM};
  19.   static int jungle[10] =
  20.     {ANTEATER,PARROT,MAMBA,ANT,ANT,HYENA,HYENA,ELEPHANT,LION,RANDOM};
  21.   static int river[10] =
  22.     {QUAIL,TROUT,TROUT,MANOWAR,BASS,BASS,CROC,CROC,BRIGAND,RANDOM};
  23.   static int swamp[10] =
  24.     {BASS,BASS,CROC,CROC,BOGTHING,ANT,ANT,RANDOM,RANDOM,RANDOM};
  25.   static int desert[10] =
  26.     {HAWK,HAWK,CAMEL,CAMEL,HYENA,HYENA,LION,LION,RANDOM,RANDOM};
  27.   static int tundra[10] =
  28.     {WOLF,WOLF,BEAR,BEAR,DEER,DEER,RANDOM,RANDOM,RANDOM,RANDOM};
  29.   static int mountain[10] =
  30.     {BUNNY,SHEEP,WOLF,WOLF,HAWK,HAWK,HAWK,RANDOM,RANDOM,RANDOM};
  31.   int *monsters,i,nummonsters;
  32.  
  33.   nummonsters = (random_range(5)+1) * (random_range(3)+1);
  34.  
  35.   switch(terrain) {
  36.   case PLAINS: monsters = plains; break;
  37.   case FOREST: monsters = forest; break;
  38.   case JUNGLE: monsters = jungle; break;
  39.   case RIVER: monsters = river; break;
  40.   case SWAMP: monsters = swamp; break;
  41.   case MOUNTAINS: case PASS: case VOLCANO: monsters = mountain; break;
  42.   case DESERT: monsters = desert; break;
  43.   case TUNDRA: monsters = tundra; break;
  44.   default: monsters = NULL;
  45.   }
  46.   for(i=0;i<nummonsters;i++) {
  47.     tml = ((pml) checkmalloc(sizeof(mltype)));
  48.     tml->m = ((pmt) checkmalloc(sizeof(montype)));
  49.     if (monsters == NULL) tml->m = 
  50.       m_create(random_range(WIDTH),random_range(LENGTH),TRUE,difficulty());
  51.     else {
  52.       tml->m = make_creature(*(monsters+random_range(10)));
  53.       tml->m->x = random_range(WIDTH);
  54.       tml->m->y = random_range(LENGTH);
  55.     }
  56.     Level->site[tml->m->x][tml->m->y].creature = tml->m;
  57.     tml->m->sense = WIDTH;
  58.     if (m_statusp(tml->m,ONLYSWIM)) {
  59.       Level->site[tml->m->x][tml->m->y].locchar = WATER;
  60.       Level->site[tml->m->x][tml->m->y].p_locf = L_WATER;
  61.       lset(tml->m->x, tml->m->y, CHANGED);
  62.     }
  63.  
  64.     tml->next = ml;
  65.     ml = tml;
  66.   }
  67.   Level->mlist = ml;
  68. }
  69.  
  70.  
  71.  
  72. /* monstertype is more or less Current_Dungeon */
  73. /* The caves and sewers get harder as you penetrate them; the castle
  74. is completely random, but also gets harder as it is explored;
  75. the astral and the volcano just stay hard... */
  76. void populate_level(monstertype)
  77. int monstertype;
  78. {
  79.   pml head,tml;
  80.   int i,j,k,monsterid,nummonsters=(random_range(difficulty()/3)+1)*3+8;
  81.  
  82.   if (monstertype == E_CASTLE) nummonsters += 10;
  83.   else if (monstertype == E_ASTRAL) nummonsters += 10;
  84.   else if (monstertype == E_VOLCANO) nummonsters += 20;
  85.  
  86.   head = tml = ((pml) checkmalloc(sizeof(mltype)));
  87.  
  88.   for(k=0;k<nummonsters;k++) {
  89.  
  90.     findspace(&i,&j,-1);
  91.  
  92.     switch(monstertype) {
  93.     case E_CAVES:
  94.       if (Level->depth*10+random_range(100) > 150) 
  95.     monsterid = ML3+7; /* Goblin Shaman*/
  96.       else if (Level->depth*10+random_range(100) > 100) 
  97.     monsterid = ML2+9; /* Goblin Chieftain */
  98.       else if (random_range(100) > 50) monsterid = ML1+6; /* Goblin */
  99.       else monsterid = -1; /* IE, random monster */
  100.       break;
  101.     case E_SEWERS:
  102.       if (! random_range(3)) monsterid = -1;
  103.       else switch(random_range(Level->depth+3)) {
  104.       case 0: monsterid = ML1+3; break; /* sewer rat */
  105.       case 1: monsterid = ML1+4; break; /* aggravator fungus */
  106.       case 2: monsterid = ML1+5; break; /* blipper rat */
  107.       case 3: monsterid = ML2+1; break; /* night gaunt */
  108.       case 4: monsterid = ML2+5; break; /* transparent nasty */
  109.       case 5: monsterid = ML2+8; break; /* murk fungus */
  110.       case 6: monsterid = ML3+1; break; /* catoblepas */
  111.       case 7: monsterid = ML3+3; break; /* acid cloud */
  112.       case 8: monsterid = ML4+3; break; /* denebian slime devil */
  113.       case 9: monsterid = ML4+8; break; /* giant crocodile */
  114.       case 10: monsterid = ML5+1; break; /* tesla monster */
  115.       case 11: monsterid = ML5+7; break; /* shadow spirit */
  116.       case 12: monsterid = ML5+8; break; /* bogthing */
  117.       case 13: monsterid = ML6+2; break; /* water elemental */
  118.       case 14: monsterid = ML6+6; break; /* triton */
  119.       case 15: monsterid = ML7+3; break; /* ROUS */
  120.       default: monsterid = -1; break;
  121.       }
  122.       break;
  123.     case E_ASTRAL:
  124.       if (random_range(2)) /* random astral creatures */
  125.     switch(random_range(12)) {
  126.     case 0: monsterid = ML3+14; break; /* thought form */
  127.     case 1: monsterid = ML4+11; break; /* astral fuzzy */
  128.     case 2: monsterid = ML4+15; break; /* ban sidhe */
  129.     case 3: monsterid = ML4+16; break; /* astral grue */
  130.     case 4: monsterid = ML5+7; break; /* shadow spirit */
  131.     case 5: monsterid = ML5+9; break; /* astral vampire */
  132.     case 6: monsterid = ML5+11; break; /* manaburst */
  133.     case 7: monsterid = ML6+9; break; /* rakshasa */
  134.     case 8: monsterid = ML7+4; break; /* illusory fiend */
  135.     case 9: monsterid = ML7+9; break; /* mirror master */
  136.     case 10: monsterid = ML7+10; break; /* elder etheric grue */
  137.     case 11: monsterid = ML8+8; break; /* shadow slayer */
  138.     }
  139.       else if (random_range(2) && (Level->depth == 1)) /* plane of earth */
  140.     monsterid = ML6+3; /* earth elemental */
  141.       else if (random_range(2) && (Level->depth == 2)) /* plane of air */
  142.     monsterid = ML6+1;  /* air elemental */
  143.       else if (random_range(2) && (Level->depth == 3)) /* plane of water */
  144.     monsterid = ML6+2;  /* water elemental */
  145.       else if (random_range(2) && (Level->depth == 4)) /* plane of fire */
  146.     monsterid = ML6+0;  /* fire elemental */
  147.       else if (random_range(2) && (Level->depth == 5)) /* deep astral */
  148.     switch (random_range(12)) {
  149.     case 0:monsterid = ML2+1; break; /* night gaunt */
  150.     case 1:monsterid = ML4+12; break; /* servant of law */
  151.     case 2:monsterid = ML4+13; break; /* servant of chaos */
  152.     case 3:monsterid = ML5+4; break; /* lesser frost demon */
  153.     case 4:monsterid = ML5+12; break; /* outer circle demon */
  154.     case 5:monsterid = ML6+10; break; /* demon serpent */
  155.     case 6:monsterid = ML6+11; break; /* angel */
  156.     case 7:monsterid = ML7+14; break; /* inner circle demon */
  157.     case 8:monsterid = ML8+5; break; /* frost demon lord */
  158.     case 9:monsterid = ML8+11; break; /* high angel */
  159.     case 10:monsterid = ML9+7; break; /* prime circle demon */
  160.     case 11:monsterid = ML9+6; break; /* archangel */
  161.     }
  162.       else monsterid = -1;
  163.       break;
  164.     case E_VOLCANO:
  165.       if (random_range(2)) {
  166.     do monsterid = random_range(ML10-ML4)+ML4;
  167.     while (Monsters[monsterid].uniqueness != COMMON);
  168.       }
  169.       else switch(random_range(Level->depth/2+2)) { /* evil & fire creatures */
  170.       case 0: monsterid = ML4+5; break;
  171.       case 1: monsterid = ML4+6; break;
  172.       case 2: monsterid = ML5+0; break;
  173.       case 3: monsterid = ML5+4; break;
  174.       case 4: monsterid = ML5+5; break;
  175.       case 5: monsterid = ML5+10; break;
  176.       case 6: monsterid = ML6+0; break;
  177.       case 7: monsterid = ML6+5; break;
  178.       case 8: monsterid = ML6+9; break;
  179.       case 9: monsterid = ML6+10; break;
  180.       case 10: monsterid = ML7+1; break;
  181.       case 11: monsterid = ML7+6; break;
  182.       case 12: monsterid = ML7+11; break;
  183.       case 13: monsterid = ML7+12; break;
  184.       case 14: monsterid = ML7+14; break;
  185.       case 15: monsterid = ML7+3; break; 
  186.       case 16: monsterid = ML8+3; break; 
  187.       case 17: monsterid = ML8+5; break; 
  188.       case 18: monsterid = ML8+8; break; 
  189.       case 19: monsterid = ML7+3; break; 
  190.       case 20: monsterid = ML9+5; break; 
  191.       case 21: monsterid = ML9+7; break; 
  192.       default: monsterid = -1; break;
  193.       }
  194.       break;      
  195.     case E_CASTLE: 
  196.       if (random_range(4)==1) {
  197.     if (difficulty() < 5)
  198.       monsterid = ML2+7;
  199.     else if (difficulty() < 6)
  200.       monsterid = ML5+6;
  201.     else if (difficulty() < 8)
  202.       monsterid = ML6+0;
  203.     else monsterid = ML9+4;
  204.       }
  205.       else monsterid = -1;
  206.     break;
  207.  
  208.     default: monsterid = -1; break;
  209.     }
  210.     
  211.     if (monsterid > -1)
  212.       Level->site[i][j].creature = make_creature(monsterid);
  213.     else Level->site[i][j].creature = m_create(i,j,TRUE,difficulty());
  214.  
  215.  
  216.     Level->site[i][j].creature->x = i;
  217.     Level->site[i][j].creature->y = j;
  218.     
  219.     if (m_statusp(Level->site[i][j].creature,ONLYSWIM)) {
  220.       Level->site[i][j].locchar = WATER;
  221.       Level->site[i][j].p_locf = L_WATER;
  222.       lset(i, j, CHANGED);
  223.     }
  224.     
  225.     tml->next = ((pml) checkmalloc(sizeof(mltype)));
  226.     tml->next->m = Level->site[i][j].creature;
  227.     tml = tml->next;
  228.   }
  229.   
  230.   if (Level->mlist==NULL) {
  231.     tml->next = NULL;
  232.     Level->mlist = head->next;
  233.   }
  234.   else {
  235.     tml->next = Level->mlist;
  236.     Level->mlist = head->next;
  237.   }
  238. }
  239.  
  240.  
  241.  
  242. /* Add a wandering monster possibly */
  243. void wandercheck()
  244. {
  245.   int x,y;
  246.   pml tml;
  247.   if (random_range(MaxDungeonLevels) < difficulty()) {
  248.     findspace(&x,&y,-1);
  249.     tml = ((pml) checkmalloc(sizeof(mltype)));
  250.     tml->next = Level->mlist;
  251.     tml->m = Level->site[x][y].creature = m_create(x,y,WANDERING,difficulty());
  252.     Level->mlist = tml;    
  253.   }
  254. }
  255.  
  256.  
  257.  
  258. /* call make_creature and place created monster on Level->mlist and Level */
  259. void make_site_monster(i,j,mid)
  260. int i,j,mid;
  261. {
  262.   pml ml = ((pml) checkmalloc(sizeof(mltype)));
  263.   pmt m;
  264.   if (mid > -1)  Level->site[i][j].creature = (m = make_creature(mid));
  265.   else Level->site[i][j].creature = (m = m_create(i,j,WANDERING,difficulty()));
  266.   m->x = i;
  267.   m->y = j;
  268.   ml->m = m;
  269.   ml->next = Level->mlist;
  270.   Level->mlist = ml;
  271. }
  272.  
  273.  
  274. /* make and return an appropriate monster for the level and depth*/
  275. /* called by populate_level, doesn't actually add to mlist for some reason*/
  276. /* eventually to be more intelligent */
  277. pmt m_create(x,y,kind,level)
  278. int x,y,kind,level;
  279. {
  280.   pmt newmonster;
  281.   int monster_range;
  282.   int mid;
  283.  
  284.   switch(level) {
  285.     case 0:monster_range = ML1; break;
  286.     case 1:monster_range = ML2; break;
  287.     case 2:monster_range = ML3; break;
  288.     case 3:monster_range = ML4; break;
  289.     case 4:monster_range = ML5; break;
  290.     case 5:monster_range = ML6; break;
  291.     case 6:monster_range = ML7; break;
  292.     case 7:monster_range = ML8; break;
  293.     case 8:monster_range = ML9; break;
  294.     case 9:monster_range = ML10; break;
  295.     default:monster_range = NUMMONSTERS; break;
  296.   }
  297.  
  298.   do 
  299.     mid = random_range(monster_range);
  300.   while (Monsters[mid].uniqueness != COMMON); 
  301.   newmonster = make_creature(mid);
  302.  
  303.   /* no duplicates of unique monsters */
  304.   if (kind == WANDERING) m_status_set(newmonster,WANDERING);
  305.   newmonster->x = x;
  306.   newmonster->y = y;
  307.   return(newmonster);
  308. }
  309.  
  310.  
  311.  
  312. /* make creature # mid, totally random if mid == -1 */
  313. /* make creature allocates space for the creature */
  314. pmt make_creature(mid)
  315. int mid;
  316. {
  317.   pmt newmonster = ((pmt) checkmalloc(sizeof(montype)));
  318.   pob ob;
  319.   int i,treasures;
  320.  
  321.   if (mid == -1) mid = random_range(ML9);
  322.   *newmonster = Monsters[mid];
  323.   if ((mid == ML6+11) || (mid == ML8+11) || (mid == ML9+6)) {
  324.     /* aux1 field of an angel is its deity */
  325.     if (Current_Environment == E_TEMPLE)
  326.       newmonster->aux1 = Country[LastCountryLocX][LastCountryLocY].aux;
  327.     else
  328.       newmonster->aux1 = random_range(6)+1;
  329.     strcpy(Str3,Monsters[mid].monstring);
  330.     switch(newmonster->aux1) {
  331.     case ODIN: strcat(Str3," of Odin"); break;
  332.     case SET: strcat(Str3," of Set"); break;
  333.     case HECATE: strcat(Str3," of Hecate"); break;
  334.     case ATHENA: strcat(Str3," of Athena"); break;
  335.     case DESTINY: strcat(Str3," of Destiny"); break;
  336.     case DRUID: strcat(Str3," of the Balance"); break;
  337.     }
  338.     newmonster->monstring = salloc(Str3);
  339.   }
  340.   else if (mid == ML0+7 || mid == ML3+13) { 
  341.     /* generic 0th level human, or a were-human */
  342.     newmonster->monstring = mantype();
  343.     strcpy(Str1,"dead ");
  344.     strcat(Str1,newmonster->monstring);
  345.     newmonster->corpsestr = salloc(Str1);
  346.   }
  347.   else if ((newmonster->monchar&0xff) == '!') {
  348.     /* the nymph/satyr and incubus/succubus */
  349.     if (Player.preference == 'f' ||
  350.     (Player.preference != 'm' && random_range(2))) {
  351.       newmonster->monchar = 'n'|COL_RED;
  352.       newmonster->monstring = "nymph";
  353.       newmonster->corpsestr = "dead nymph";
  354.     }
  355.     else {
  356.       newmonster->monchar = 's'|COL_RED;
  357.       newmonster->monstring = "satyr";
  358.       newmonster->corpsestr = "dead satyr";
  359.     }
  360.     if (newmonster->id == ML4+6) {
  361.       if ((newmonster->monchar&0xff) == 'n')
  362.     newmonster->corpsestr = "dead succubus";
  363.       else newmonster->corpsestr = "dead incubus";
  364.     }
  365.   }
  366.   if (mid == NPC)
  367.     make_log_npc(newmonster);
  368.   else if (mid == HISCORE_NPC)
  369.     make_hiscore_npc(newmonster, random_range(15));
  370.   else {
  371.     if (newmonster->sleep < random_range(100))
  372.       m_status_set(newmonster,AWAKE);
  373.     if (newmonster->startthing > -1 &&
  374.       Objects[newmonster->startthing].uniqueness <= UNIQUE_MADE) {
  375.       ob = ((pob) checkmalloc(sizeof(objtype)));    
  376.       *ob = Objects[newmonster->startthing];
  377.       m_pickup(newmonster,ob);
  378.     }
  379.     treasures = random_range(newmonster->treasure);
  380.     for(i=0;i<treasures;i++) {
  381.       do {
  382.         ob = (pob) (create_object(newmonster->level));
  383.         if (ob && ob->uniqueness != COMMON) {
  384.           free(ob);
  385.           ob = NULL;
  386.         }
  387.       } while (!ob);
  388.       m_pickup(newmonster,ob);
  389.     }
  390.   }
  391.   newmonster->click = (Tick + 1) % 50;
  392.   return(newmonster);
  393. }
  394.  
  395.  
  396.  
  397.  
  398. /* drop treasures randomly onto level */
  399. void stock_level()
  400. {
  401.   int i,j,k,numtreasures=2*random_range(difficulty()/4)+4;
  402.  
  403.   /* put cash anywhere, including walls, put other treasures only on floor */
  404.   for (k=0;k<numtreasures+10;k++) {
  405.     do {
  406.       i = random_range(WIDTH);
  407.       j = random_range(LENGTH);
  408.     } while (Level->site[i][j].locchar != FLOOR);
  409.     make_site_treasure(i,j,difficulty());
  410.     i = random_range(WIDTH);
  411.     j = random_range(LENGTH);
  412.     Level->site[i][j].things = ((pol) checkmalloc(sizeof(oltype)));
  413.     Level->site[i][j].things->thing = ((pob) checkmalloc(sizeof(objtype)));
  414.     make_cash(Level->site[i][j].things->thing,difficulty());
  415.     Level->site[i][j].things->next = NULL;
  416.     /* caves have more random cash strewn around */
  417.     if (Current_Dungeon == E_CAVES) {
  418.       i = random_range(WIDTH);
  419.       j = random_range(LENGTH);
  420.       Level->site[i][j].things = ((pol) checkmalloc(sizeof(oltype)));
  421.       Level->site[i][j].things->thing = ((pob) checkmalloc(sizeof(objtype)));
  422.       make_cash(Level->site[i][j].things->thing,difficulty());
  423.       Level->site[i][j].things->next = NULL;
  424.       i = random_range(WIDTH);
  425.       j = random_range(LENGTH);
  426.       Level->site[i][j].things = ((pol) checkmalloc(sizeof(oltype)));
  427.       Level->site[i][j].things->thing = ((pob) checkmalloc(sizeof(objtype)));
  428.       make_cash(Level->site[i][j].things->thing,difficulty());
  429.       Level->site[i][j].things->next = NULL;
  430.     }
  431.   }
  432. }
  433.  
  434.  
  435. /* make a new object (of at most level itemlevel) at site i,j on level*/
  436. void make_site_treasure(i,j,itemlevel)
  437. int i,j,itemlevel;
  438. {
  439.   pol tmp = ((pol) checkmalloc(sizeof(oltype)));
  440.   do tmp->thing = ((pob) create_object(itemlevel));
  441.   while (!tmp->thing);
  442.   tmp->next = Level->site[i][j].things;
  443.   Level->site[i][j].things = tmp;
  444. }
  445.  
  446. /* make a specific new object at site i,j on level*/
  447. void make_specific_treasure(i,j,itemid)
  448. int i,j,itemid;
  449. {
  450.   pol tmp;
  451.   if (Objects[itemid].uniqueness == UNIQUE_TAKEN)
  452.     return;
  453.   tmp = ((pol) checkmalloc(sizeof(oltype)));
  454.   tmp->thing = ((pob) checkmalloc(sizeof(objtype)));
  455.   *(tmp->thing) = Objects[itemid];
  456.   tmp->next = Level->site[i][j].things;
  457.   Level->site[i][j].things = tmp;
  458. }
  459.  
  460.  
  461.  
  462. #ifndef MSDOS
  463. /* returns a "level of difficulty" based on current environment
  464.    and depth in dungeon. Is somewhat arbitrary. value between 1 and 10.
  465.    May not actually represent real difficulty, but instead level
  466.    of items, monsters encountered.    */
  467. int difficulty()
  468. {
  469.   int depth = 1;
  470.   if (Level != NULL) depth = Level->depth;
  471.   switch(Current_Environment) {
  472.   case E_COUNTRYSIDE: return(7);
  473.   case E_CITY: return(3);
  474.   case E_VILLAGE: return(1);
  475.   case E_TACTICAL_MAP: return(7);
  476.   case E_SEWERS: return(depth/6)+3;
  477.   case E_CASTLE: return(depth/4)+4;
  478.   case E_CAVES: return(depth/3)+1;
  479.   case E_VOLCANO: return(depth/4)+5;
  480.   case E_ASTRAL: return(8);
  481.   case E_ARENA: return(5);
  482.   case E_HOVEL: return(3);
  483.   case E_MANSION: return(7);
  484.   case E_HOUSE: return(5);
  485.   case E_DLAIR: return(9);
  486.   case E_ABYSS: return(10);
  487.   case E_STARPEAK: return(9);
  488.   case E_CIRCLE: return(8);
  489.   case E_MAGIC_ISLE: return(8);
  490.   case E_TEMPLE: return(8);
  491.   default: return(3);
  492.   }
  493. }
  494. #endif
  495.